use std::fmt::Debug;
use std::future::Future;
use std::pin::Pin;
use tokio::task::JoinHandle;
use std::sync::Arc;
use crate::dispatcher::{ThreadPoolDispatcher, SynchronousDispatcher};
use tracing::error;

// 重新导出DispatcherTrait，使其可以被其他模块访问
pub use crate::dispatcher::DispatcherTrait;

/// Dispatcher enum for different dispatcher types
#[derive(Debug)]
pub enum DispatcherEnum {
    /// Thread pool dispatcher
    ThreadPool(Arc<ThreadPoolDispatcher>),
    /// Synchronous dispatcher
    Synchronous(Arc<SynchronousDispatcher>),
}

impl DispatcherTrait for DispatcherEnum {
    fn schedule_boxed(
        &self,
        f: Box<dyn FnOnce() -> Pin<Box<dyn Future<Output = ()> + Send + Unpin>> + Send + 'static>,
    ) -> JoinHandle<()> {
        match self {
            DispatcherEnum::ThreadPool(d) => d.schedule_boxed(f),
            DispatcherEnum::Synchronous(d) => d.schedule_boxed(f),
        }
    }
    
    fn throughput(&self) -> usize {
        match self {
            DispatcherEnum::ThreadPool(d) => d.throughput(),
            DispatcherEnum::Synchronous(d) => d.throughput(),
        }
    }
}

impl DispatcherEnum {
    /// Create a new thread pool dispatcher
    pub fn thread_pool() -> Self {
        Self::ThreadPool(Arc::new(ThreadPoolDispatcher::new(300)))
    }
    
    /// Create a synchronous dispatcher
    pub fn synchronous() -> Self {
        Self::Synchronous(Arc::new(SynchronousDispatcher::new(300)))
    }
    
    /// Schedule a task with the dispatcher
    pub async fn schedule<F>(&self, f: F)
    where
        F: FnOnce() -> Pin<Box<dyn Future<Output = ()> + Send + Unpin>> + Send + 'static,
    {
        let result = self.schedule_boxed(Box::new(f)).await;
        if let Err(e) = result {
            error!("Error in dispatcher schedule: {:?}", e);
        }
    }
}

/// Create default dispatchers as trait objects
pub fn default_thread_pool() -> Arc<dyn DispatcherTrait> {
    Arc::new(DispatcherEnum::thread_pool())
}

/// Create default synchronous dispatcher as trait object
pub fn default_synchronous() -> Arc<dyn DispatcherTrait> {
    Arc::new(DispatcherEnum::synchronous())
} 